package com.googlecode.curvedmetromaps.core.model.importer;

import java.util.ArrayList;
import java.util.HashMap;
import playn.core.Json;
import playn.core.PlayN;

import com.googlecode.curvedmetromaps.core.model.MetroLine;
import com.googlecode.curvedmetromaps.core.model.MetroMap;
import com.googlecode.curvedmetromaps.core.model.MetroStation;

/**
 * Parses a custom JSON format. For example: { "caption": "ToyExample",
 * "stations": [ {"id":"orange01", "x": 1, "y": 1}, {"id":"orange02", "x": 0,
 * "y": 0}, {"id":"orange03", "x": 1, "y": 1} ], "lines": [
 * {"id":"orange","color":"#FFA500","stations":[ "orange01", "orange02",
 * "orange03" ]} ] }
 */
public class JsonMapParser extends MapParser {

	@Override
	public void parse(String resource, final MetroMap map) {
		// Parse text to JSON
		Json.Object doc = PlayN.json().parse(resource);
		// Parse JSON to MetroMap
		parseJson(doc, map);
	}

	private void parseJson(Json.Object doc, final MetroMap map) {
		// parse metrostations into a hashmap
		HashMap<String, MetroStation> metroStations = new HashMap<String, MetroStation>();
		Json.Array jsonStations = doc.getArray("stations");
		for (int i = 0; i < jsonStations.length(); i++) {
			Json.Object jsonStation = jsonStations.getObject(i);
			String id = jsonStation.getString("id");
			String label = jsonStation.getString("label");

			// Get Cartesian coordinates
			float x, y;
			String latStr = jsonStation.getString("lat");
			String lngStr = jsonStation.getString("lng");
			if (latStr != null && lngStr != null) {
				double lng = ImportUtil.parseCoordinate(lngStr);
				double lat = ImportUtil.parseCoordinate(latStr);
				double[] xy = Mercator.merc(lng, lat);
				x = (float) xy[0];
				y = (float) xy[1];
			} else {
				x = jsonStation.getNumber("x");
				y = jsonStation.getNumber("y");
			}

			MetroStation m = new MetroStation(x, y, id);
			m.label = label;
			metroStations.put(id, m);
		}

		// parse metrolines
		Json.Array jsonLines = doc.getArray("lines");
		HashMap<String, MetroLine> metroLines = new HashMap<String, MetroLine>();
		for (int i = 0; i < jsonLines.length(); i++) {
			Json.Object jsonLine = jsonLines.getObject(i);
			String id = jsonLine.getString("id");
			Json.Array stations = jsonLine.getArray("stations");

			// Parse color
			Json.Array a = jsonLine.getArray("color");
			int color = jsonLine.getInt("color");
			if (a != null) {
				String[] rgb = new String[3];
				for (int j = 0; j < 3; j++) {
					rgb[j] = a.getString(j);
					if (rgb[j] == null)
						rgb[j] = String.valueOf(a.getInt(j));
				}
				color = ImportUtil.parseColor(rgb);
			} else {
				String s = jsonLine.getString("color");
				if (s != null) {
					color = Long.decode(s).intValue();
				}
			}

			// Read stations
			ArrayList<MetroStation> stationList = new ArrayList<MetroStation>();
			for (int j = 0; j < stations.length(); j++) {
				String str = stations.getString(j);
				MetroStation m = metroStations.get(str);
				stationList.add(m);
			}

			// Convert list of stations to a line
			MetroLine metroLine = new MetroLine(stationList);
			metroLine.color = color;
			metroLines.put(id, metroLine);
		}

		// Create MetroMap from collections of stations and lines.
		map.initialize(metroStations.values(), metroLines.values());
	}
}
